<!DOCTYPE html>
<html lang="zh-cn" itemscope itemtype="http://schema.org/WebPage">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title> - 友知弄</title>
  

<meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>

<meta name="MobileOptimized" content="width"/>
<meta name="HandheldFriendly" content="true"/>


<meta name="applicable-device" content="pc,mobile">

<meta name="theme-color" content="#f8f5ec" />
<meta name="msapplication-navbutton-color" content="#f8f5ec">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">

<meta name="mobile-web-app-capable" content="yes">

<meta name="author" content="yixy" />
  <meta name="description" content="OS笔记(7)——内存的抽象与管理 由于register和cache的管理由硬件完成，所以我们由内存管理开始我们对操作系统存储管理的介绍。
1. 无内存抽象 最早的内存管理是直面物理内存的，即没有内存抽象。此时的内存组织方式出现过以下几种。
 “用户程序&#43;RAM”：用于大型机和小型机。 “ROM&#43;用户程序”：用于掌上设备或嵌入式设备。 “ROM&#43;用户程序&#43;RAM”：用于早期PC。  直接使用物理内存面临两个问题，第一，用户可以寻址内存的每个字节，导致系统可以很容易地被（故意或偶然地）破坏，（除非使用特殊的硬件保护，如IBM360的锁键模式）；第二，系统想要并发运行多道程序是很困难的。
2. 内存抽象：虚拟地址空间 用户程序在运行时其实不希望介入到复杂的存储器管理过程中，作为普通的程序，它需要的是一个简单的执行环境，有一个单一的地址空间、有自己的CPU，好像整个程序占有整个计算机而不用关心其它的程序（当然程序间通信的部分除外，因为这是程序主动要求跟其它程序通信和联系）。进程模型是对CPU的一个抽象，而地址空间则为程序创造了一种抽象的内存。
 虚拟地址空间：虚拟地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的虚拟地址空间，并且这个虚拟地址空间独立于其它进程的地址空间（除了在一些特殊情况下进程需要共享它们的地址空间外）。  进程的虚拟地址并不是直接被送到内存总线上，而是被送到内存管理单元（MMU），MMU把虚拟地址映射为物理内存地址。
3. 内存地址重定位 可以采用重定位技术以支持多道程序在系统中运行。其中，动态重定位技术还提供了地址保护机制。
 静态重定位：指在程序执行之前，在装载过程中完成程序地址重定位。在程序装载到内存时，系统为每个程序地址加上一个偏移量常数。 动态重定位：指在程序运行中进行地址重定位。当一个进程运行时，程序在内存中的起始物理位置读取到基址寄存器中，程序的长度读取到界限寄存器中。进程每次访问内存时，CPU硬件会在把地址发送到内存总线前，自动把基址值加到进程发出的地址上，同时检查程序提供的地址是否合法（是否超过界限值）。  静态重定位方式会减慢装载速度，并且没有地址保护机制。动态重定位具有地址保护机制，但是每次访问内存时需要进行加法和比较运算（加法在不使用特殊电路时会很慢），导致重定位效率低下。
4. 交换（swap）技术 如果计算机物理内存足够大，可以保存所有进程，那么使用地址空间抽象并运用内存地址重定位技术似乎已经可以解决所有问题了。但实际上，所有进程所需的内存数量总是远远超出存储器能够支持的范围的。可以使用交换技术解决内存超载的问题。
 交换（swapping）技术：一个进程在内存中运行一段时间后，再将该进程保存到磁盘。这样，不在运行的进程就不会占用内存了。  交换会在内存中产生很多空洞（hole）区域。可以采用内存紧缩的技术解决这种碎片化的空洞区，但是这个操作会耗费大量的CPU时间，所以通常情况下是不会进行的。
 内存紧缩（memory compaction）：通过把所有的进程尽可能向某个方向移动，可能将小的空洞合成一大块，该技术被称为内存紧缩。  许多程序设计语言允许从堆中动态地分配内存，那么当进程空间试图增大时，交换技术可能会面临问题。为增长预留空间是一个解决方案。
5. 虚拟内存技术：分页 前面说过，重定位的效率不高，实际上该技术在内存管理上已经不太常用了。而交换技术也面临着进程空间膨胀的难题。虚拟内存技术是另一种可以解决内存超载问题的技术。该策略甚至能使程序在只有一部分被调入内存的情况下运行。
 虚拟内存（virtual memory）技术：将进程的虚拟地址空间分割成多个块，每块被称作一个页面（page）。每一页有连续的地址范围。这些页面被映射到物理内存（在物理内存中对应的单元称为页框page frame），但并不是所有的页面都必须在内存中才能运行程序。当进程引用到一部分在物理内存的页面时，由硬件立刻执行必要的映射。当进程引用到一部分不再物理内存的页面时，指令执行失败，进程陷入缺页中断，由OS负责将缺失的部分装入物理内存并重新执行失败的指令。内存和磁盘之间的交换总是以正规页面为单元进行的。  页面的大小一般从512B到64KB。
 页表：页表是一个数据结构，其目的是把page映射为page frame。从数学角度说，页表是一个函数，它的参数是虚拟页号，结果是page frame。注意，每个进程都拥有自己的页表。  上图展示了虚拟地址（虚拟页号&#43;页内偏移量）通过页表转换为物理地址（页框号&#43;页内偏移量）的过程。
在分页式系统中，有两个问题需要考虑：虚拟地址到物理地址的映射必须非常快；需要考虑应对虚拟地址空间很大的情况。
5.1 加速分页过程：TLB
通常，页表被设计在内存中，每次虚拟地址到物理地址的映射都必须访问内存，这样会导致性能低下。考虑将页表使用一组硬件快速寄存器实现是一种思路，但是考虑到昂贵的代价显然不可能将每个进程的页表都用这种方式实现。一个显而易见的方案是，使用一组硬件寄存器组成单一的页表，当启动一个进程时，操作系统将该进程在内存中的页表副本载入寄存器中。这样，该进程的地址映射过程中不再需要访问内存中的页表了，但是这样又增加了进程间切换时的开销。目前，一种常见的解决方案是使用TLB。
 TLB（Translation Lookaside Buffer，转换检测缓冲区）：“大多数程序总是对少量的页面进行多次访问”，基于这样的思想，在MMU中设置一个小型的硬件设备，它包含少量的表项，该设备就是TLB。地址映射首先在TLB中由硬件进行转换，如果TLB中匹配不到才会到去访问内存表项。  注意，最初，对TLB的管理和TLB失效处理都完全由MMU硬件来实现，只有在内存中没有找到某个页面时，才会陷入到操作系统中。后来，很多机器的几乎所有的页面管理都在软件中实现了。这些机器上，TLB表项被显示地装载。当发生TLB访问失效的时候不再是MMU到页表中查找并取出数据，而是生成一个TLB失效并将问题提交给操作系统解决。事实证明，如果TLB大（比如64个表项）到可以减少失效率，TLB的软件管理也能够变得足够有效。
5.2 处理巨大的虚拟地址空间：多级页表与倒排页表
以32位虚地址为例，后12位为偏移量，则页面大小为4KB，页面数量为2^20。
采用“多级页表”的原因是避免把全部页表一直保存在内存中，那些从不需要的页表项将被存储在磁盘。一般，页表级数不超过4级。
当虚拟地址空间是2^64字节时（64位计算机），假设页面大小是4KB，需要有2^52个表项。即使采用了多级页表，存储在磁盘上的表项数据所占用的空间也是巨额的。此时，解决方案之一是使用倒排页表（invertered page table）。在这种设计之中，实际内存里每一个页框有一个表项，而不是每一个虚拟页面有一个表项。" />

  <meta name="keywords" content="essay, notes" />






<meta name="generator" content="Hugo 0.56.1" />


<link rel="canonical" href="https://yixy.github.io/youzhilane/post/01%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/os%E7%AC%94%E8%AE%B06%E5%86%85%E5%AD%98%E7%9A%84%E6%8A%BD%E8%B1%A1%E4%B8%8E%E7%AE%A1%E7%90%86/" />



<link rel="icon" href="/youzhilane/favicon.ico" />











<link rel="stylesheet" href="/youzhilane/sass/jane.min.af20b78e95c84de86b00a0242a4a77bd2601700e1b250edf27537d957ac0041d.css" integrity="sha256-ryC3jpXITehrAKAkKkp3vSYBcA4bJQ7fJ1N9lXrABB0=" media="screen" crossorigin="anonymous">





<meta property="og:title" content="" />
<meta property="og:description" content="OS笔记(7)——内存的抽象与管理 由于register和cache的管理由硬件完成，所以我们由内存管理开始我们对操作系统存储管理的介绍。
1. 无内存抽象 最早的内存管理是直面物理内存的，即没有内存抽象。此时的内存组织方式出现过以下几种。
 “用户程序&#43;RAM”：用于大型机和小型机。 “ROM&#43;用户程序”：用于掌上设备或嵌入式设备。 “ROM&#43;用户程序&#43;RAM”：用于早期PC。  直接使用物理内存面临两个问题，第一，用户可以寻址内存的每个字节，导致系统可以很容易地被（故意或偶然地）破坏，（除非使用特殊的硬件保护，如IBM360的锁键模式）；第二，系统想要并发运行多道程序是很困难的。
2. 内存抽象：虚拟地址空间 用户程序在运行时其实不希望介入到复杂的存储器管理过程中，作为普通的程序，它需要的是一个简单的执行环境，有一个单一的地址空间、有自己的CPU，好像整个程序占有整个计算机而不用关心其它的程序（当然程序间通信的部分除外，因为这是程序主动要求跟其它程序通信和联系）。进程模型是对CPU的一个抽象，而地址空间则为程序创造了一种抽象的内存。
 虚拟地址空间：虚拟地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的虚拟地址空间，并且这个虚拟地址空间独立于其它进程的地址空间（除了在一些特殊情况下进程需要共享它们的地址空间外）。  进程的虚拟地址并不是直接被送到内存总线上，而是被送到内存管理单元（MMU），MMU把虚拟地址映射为物理内存地址。
3. 内存地址重定位 可以采用重定位技术以支持多道程序在系统中运行。其中，动态重定位技术还提供了地址保护机制。
 静态重定位：指在程序执行之前，在装载过程中完成程序地址重定位。在程序装载到内存时，系统为每个程序地址加上一个偏移量常数。 动态重定位：指在程序运行中进行地址重定位。当一个进程运行时，程序在内存中的起始物理位置读取到基址寄存器中，程序的长度读取到界限寄存器中。进程每次访问内存时，CPU硬件会在把地址发送到内存总线前，自动把基址值加到进程发出的地址上，同时检查程序提供的地址是否合法（是否超过界限值）。  静态重定位方式会减慢装载速度，并且没有地址保护机制。动态重定位具有地址保护机制，但是每次访问内存时需要进行加法和比较运算（加法在不使用特殊电路时会很慢），导致重定位效率低下。
4. 交换（swap）技术 如果计算机物理内存足够大，可以保存所有进程，那么使用地址空间抽象并运用内存地址重定位技术似乎已经可以解决所有问题了。但实际上，所有进程所需的内存数量总是远远超出存储器能够支持的范围的。可以使用交换技术解决内存超载的问题。
 交换（swapping）技术：一个进程在内存中运行一段时间后，再将该进程保存到磁盘。这样，不在运行的进程就不会占用内存了。  交换会在内存中产生很多空洞（hole）区域。可以采用内存紧缩的技术解决这种碎片化的空洞区，但是这个操作会耗费大量的CPU时间，所以通常情况下是不会进行的。
 内存紧缩（memory compaction）：通过把所有的进程尽可能向某个方向移动，可能将小的空洞合成一大块，该技术被称为内存紧缩。  许多程序设计语言允许从堆中动态地分配内存，那么当进程空间试图增大时，交换技术可能会面临问题。为增长预留空间是一个解决方案。
5. 虚拟内存技术：分页 前面说过，重定位的效率不高，实际上该技术在内存管理上已经不太常用了。而交换技术也面临着进程空间膨胀的难题。虚拟内存技术是另一种可以解决内存超载问题的技术。该策略甚至能使程序在只有一部分被调入内存的情况下运行。
 虚拟内存（virtual memory）技术：将进程的虚拟地址空间分割成多个块，每块被称作一个页面（page）。每一页有连续的地址范围。这些页面被映射到物理内存（在物理内存中对应的单元称为页框page frame），但并不是所有的页面都必须在内存中才能运行程序。当进程引用到一部分在物理内存的页面时，由硬件立刻执行必要的映射。当进程引用到一部分不再物理内存的页面时，指令执行失败，进程陷入缺页中断，由OS负责将缺失的部分装入物理内存并重新执行失败的指令。内存和磁盘之间的交换总是以正规页面为单元进行的。  页面的大小一般从512B到64KB。
 页表：页表是一个数据结构，其目的是把page映射为page frame。从数学角度说，页表是一个函数，它的参数是虚拟页号，结果是page frame。注意，每个进程都拥有自己的页表。  上图展示了虚拟地址（虚拟页号&#43;页内偏移量）通过页表转换为物理地址（页框号&#43;页内偏移量）的过程。
在分页式系统中，有两个问题需要考虑：虚拟地址到物理地址的映射必须非常快；需要考虑应对虚拟地址空间很大的情况。
5.1 加速分页过程：TLB
通常，页表被设计在内存中，每次虚拟地址到物理地址的映射都必须访问内存，这样会导致性能低下。考虑将页表使用一组硬件快速寄存器实现是一种思路，但是考虑到昂贵的代价显然不可能将每个进程的页表都用这种方式实现。一个显而易见的方案是，使用一组硬件寄存器组成单一的页表，当启动一个进程时，操作系统将该进程在内存中的页表副本载入寄存器中。这样，该进程的地址映射过程中不再需要访问内存中的页表了，但是这样又增加了进程间切换时的开销。目前，一种常见的解决方案是使用TLB。
 TLB（Translation Lookaside Buffer，转换检测缓冲区）：“大多数程序总是对少量的页面进行多次访问”，基于这样的思想，在MMU中设置一个小型的硬件设备，它包含少量的表项，该设备就是TLB。地址映射首先在TLB中由硬件进行转换，如果TLB中匹配不到才会到去访问内存表项。  注意，最初，对TLB的管理和TLB失效处理都完全由MMU硬件来实现，只有在内存中没有找到某个页面时，才会陷入到操作系统中。后来，很多机器的几乎所有的页面管理都在软件中实现了。这些机器上，TLB表项被显示地装载。当发生TLB访问失效的时候不再是MMU到页表中查找并取出数据，而是生成一个TLB失效并将问题提交给操作系统解决。事实证明，如果TLB大（比如64个表项）到可以减少失效率，TLB的软件管理也能够变得足够有效。
5.2 处理巨大的虚拟地址空间：多级页表与倒排页表
以32位虚地址为例，后12位为偏移量，则页面大小为4KB，页面数量为2^20。
采用“多级页表”的原因是避免把全部页表一直保存在内存中，那些从不需要的页表项将被存储在磁盘。一般，页表级数不超过4级。
当虚拟地址空间是2^64字节时（64位计算机），假设页面大小是4KB，需要有2^52个表项。即使采用了多级页表，存储在磁盘上的表项数据所占用的空间也是巨额的。此时，解决方案之一是使用倒排页表（invertered page table）。在这种设计之中，实际内存里每一个页框有一个表项，而不是每一个虚拟页面有一个表项。" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://yixy.github.io/youzhilane/post/01%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/os%E7%AC%94%E8%AE%B06%E5%86%85%E5%AD%98%E7%9A%84%E6%8A%BD%E8%B1%A1%E4%B8%8E%E7%AE%A1%E7%90%86/" />

<meta itemprop="name" content="">
<meta itemprop="description" content="OS笔记(7)——内存的抽象与管理 由于register和cache的管理由硬件完成，所以我们由内存管理开始我们对操作系统存储管理的介绍。
1. 无内存抽象 最早的内存管理是直面物理内存的，即没有内存抽象。此时的内存组织方式出现过以下几种。
 “用户程序&#43;RAM”：用于大型机和小型机。 “ROM&#43;用户程序”：用于掌上设备或嵌入式设备。 “ROM&#43;用户程序&#43;RAM”：用于早期PC。  直接使用物理内存面临两个问题，第一，用户可以寻址内存的每个字节，导致系统可以很容易地被（故意或偶然地）破坏，（除非使用特殊的硬件保护，如IBM360的锁键模式）；第二，系统想要并发运行多道程序是很困难的。
2. 内存抽象：虚拟地址空间 用户程序在运行时其实不希望介入到复杂的存储器管理过程中，作为普通的程序，它需要的是一个简单的执行环境，有一个单一的地址空间、有自己的CPU，好像整个程序占有整个计算机而不用关心其它的程序（当然程序间通信的部分除外，因为这是程序主动要求跟其它程序通信和联系）。进程模型是对CPU的一个抽象，而地址空间则为程序创造了一种抽象的内存。
 虚拟地址空间：虚拟地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的虚拟地址空间，并且这个虚拟地址空间独立于其它进程的地址空间（除了在一些特殊情况下进程需要共享它们的地址空间外）。  进程的虚拟地址并不是直接被送到内存总线上，而是被送到内存管理单元（MMU），MMU把虚拟地址映射为物理内存地址。
3. 内存地址重定位 可以采用重定位技术以支持多道程序在系统中运行。其中，动态重定位技术还提供了地址保护机制。
 静态重定位：指在程序执行之前，在装载过程中完成程序地址重定位。在程序装载到内存时，系统为每个程序地址加上一个偏移量常数。 动态重定位：指在程序运行中进行地址重定位。当一个进程运行时，程序在内存中的起始物理位置读取到基址寄存器中，程序的长度读取到界限寄存器中。进程每次访问内存时，CPU硬件会在把地址发送到内存总线前，自动把基址值加到进程发出的地址上，同时检查程序提供的地址是否合法（是否超过界限值）。  静态重定位方式会减慢装载速度，并且没有地址保护机制。动态重定位具有地址保护机制，但是每次访问内存时需要进行加法和比较运算（加法在不使用特殊电路时会很慢），导致重定位效率低下。
4. 交换（swap）技术 如果计算机物理内存足够大，可以保存所有进程，那么使用地址空间抽象并运用内存地址重定位技术似乎已经可以解决所有问题了。但实际上，所有进程所需的内存数量总是远远超出存储器能够支持的范围的。可以使用交换技术解决内存超载的问题。
 交换（swapping）技术：一个进程在内存中运行一段时间后，再将该进程保存到磁盘。这样，不在运行的进程就不会占用内存了。  交换会在内存中产生很多空洞（hole）区域。可以采用内存紧缩的技术解决这种碎片化的空洞区，但是这个操作会耗费大量的CPU时间，所以通常情况下是不会进行的。
 内存紧缩（memory compaction）：通过把所有的进程尽可能向某个方向移动，可能将小的空洞合成一大块，该技术被称为内存紧缩。  许多程序设计语言允许从堆中动态地分配内存，那么当进程空间试图增大时，交换技术可能会面临问题。为增长预留空间是一个解决方案。
5. 虚拟内存技术：分页 前面说过，重定位的效率不高，实际上该技术在内存管理上已经不太常用了。而交换技术也面临着进程空间膨胀的难题。虚拟内存技术是另一种可以解决内存超载问题的技术。该策略甚至能使程序在只有一部分被调入内存的情况下运行。
 虚拟内存（virtual memory）技术：将进程的虚拟地址空间分割成多个块，每块被称作一个页面（page）。每一页有连续的地址范围。这些页面被映射到物理内存（在物理内存中对应的单元称为页框page frame），但并不是所有的页面都必须在内存中才能运行程序。当进程引用到一部分在物理内存的页面时，由硬件立刻执行必要的映射。当进程引用到一部分不再物理内存的页面时，指令执行失败，进程陷入缺页中断，由OS负责将缺失的部分装入物理内存并重新执行失败的指令。内存和磁盘之间的交换总是以正规页面为单元进行的。  页面的大小一般从512B到64KB。
 页表：页表是一个数据结构，其目的是把page映射为page frame。从数学角度说，页表是一个函数，它的参数是虚拟页号，结果是page frame。注意，每个进程都拥有自己的页表。  上图展示了虚拟地址（虚拟页号&#43;页内偏移量）通过页表转换为物理地址（页框号&#43;页内偏移量）的过程。
在分页式系统中，有两个问题需要考虑：虚拟地址到物理地址的映射必须非常快；需要考虑应对虚拟地址空间很大的情况。
5.1 加速分页过程：TLB
通常，页表被设计在内存中，每次虚拟地址到物理地址的映射都必须访问内存，这样会导致性能低下。考虑将页表使用一组硬件快速寄存器实现是一种思路，但是考虑到昂贵的代价显然不可能将每个进程的页表都用这种方式实现。一个显而易见的方案是，使用一组硬件寄存器组成单一的页表，当启动一个进程时，操作系统将该进程在内存中的页表副本载入寄存器中。这样，该进程的地址映射过程中不再需要访问内存中的页表了，但是这样又增加了进程间切换时的开销。目前，一种常见的解决方案是使用TLB。
 TLB（Translation Lookaside Buffer，转换检测缓冲区）：“大多数程序总是对少量的页面进行多次访问”，基于这样的思想，在MMU中设置一个小型的硬件设备，它包含少量的表项，该设备就是TLB。地址映射首先在TLB中由硬件进行转换，如果TLB中匹配不到才会到去访问内存表项。  注意，最初，对TLB的管理和TLB失效处理都完全由MMU硬件来实现，只有在内存中没有找到某个页面时，才会陷入到操作系统中。后来，很多机器的几乎所有的页面管理都在软件中实现了。这些机器上，TLB表项被显示地装载。当发生TLB访问失效的时候不再是MMU到页表中查找并取出数据，而是生成一个TLB失效并将问题提交给操作系统解决。事实证明，如果TLB大（比如64个表项）到可以减少失效率，TLB的软件管理也能够变得足够有效。
5.2 处理巨大的虚拟地址空间：多级页表与倒排页表
以32位虚地址为例，后12位为偏移量，则页面大小为4KB，页面数量为2^20。
采用“多级页表”的原因是避免把全部页表一直保存在内存中，那些从不需要的页表项将被存储在磁盘。一般，页表级数不超过4级。
当虚拟地址空间是2^64字节时（64位计算机），假设页面大小是4KB，需要有2^52个表项。即使采用了多级页表，存储在磁盘上的表项数据所占用的空间也是巨额的。此时，解决方案之一是使用倒排页表（invertered page table）。在这种设计之中，实际内存里每一个页框有一个表项，而不是每一个虚拟页面有一个表项。">



<meta itemprop="wordCount" content="66">



<meta itemprop="keywords" content="" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content=""/>
<meta name="twitter:description" content="OS笔记(7)——内存的抽象与管理 由于register和cache的管理由硬件完成，所以我们由内存管理开始我们对操作系统存储管理的介绍。
1. 无内存抽象 最早的内存管理是直面物理内存的，即没有内存抽象。此时的内存组织方式出现过以下几种。
 “用户程序&#43;RAM”：用于大型机和小型机。 “ROM&#43;用户程序”：用于掌上设备或嵌入式设备。 “ROM&#43;用户程序&#43;RAM”：用于早期PC。  直接使用物理内存面临两个问题，第一，用户可以寻址内存的每个字节，导致系统可以很容易地被（故意或偶然地）破坏，（除非使用特殊的硬件保护，如IBM360的锁键模式）；第二，系统想要并发运行多道程序是很困难的。
2. 内存抽象：虚拟地址空间 用户程序在运行时其实不希望介入到复杂的存储器管理过程中，作为普通的程序，它需要的是一个简单的执行环境，有一个单一的地址空间、有自己的CPU，好像整个程序占有整个计算机而不用关心其它的程序（当然程序间通信的部分除外，因为这是程序主动要求跟其它程序通信和联系）。进程模型是对CPU的一个抽象，而地址空间则为程序创造了一种抽象的内存。
 虚拟地址空间：虚拟地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的虚拟地址空间，并且这个虚拟地址空间独立于其它进程的地址空间（除了在一些特殊情况下进程需要共享它们的地址空间外）。  进程的虚拟地址并不是直接被送到内存总线上，而是被送到内存管理单元（MMU），MMU把虚拟地址映射为物理内存地址。
3. 内存地址重定位 可以采用重定位技术以支持多道程序在系统中运行。其中，动态重定位技术还提供了地址保护机制。
 静态重定位：指在程序执行之前，在装载过程中完成程序地址重定位。在程序装载到内存时，系统为每个程序地址加上一个偏移量常数。 动态重定位：指在程序运行中进行地址重定位。当一个进程运行时，程序在内存中的起始物理位置读取到基址寄存器中，程序的长度读取到界限寄存器中。进程每次访问内存时，CPU硬件会在把地址发送到内存总线前，自动把基址值加到进程发出的地址上，同时检查程序提供的地址是否合法（是否超过界限值）。  静态重定位方式会减慢装载速度，并且没有地址保护机制。动态重定位具有地址保护机制，但是每次访问内存时需要进行加法和比较运算（加法在不使用特殊电路时会很慢），导致重定位效率低下。
4. 交换（swap）技术 如果计算机物理内存足够大，可以保存所有进程，那么使用地址空间抽象并运用内存地址重定位技术似乎已经可以解决所有问题了。但实际上，所有进程所需的内存数量总是远远超出存储器能够支持的范围的。可以使用交换技术解决内存超载的问题。
 交换（swapping）技术：一个进程在内存中运行一段时间后，再将该进程保存到磁盘。这样，不在运行的进程就不会占用内存了。  交换会在内存中产生很多空洞（hole）区域。可以采用内存紧缩的技术解决这种碎片化的空洞区，但是这个操作会耗费大量的CPU时间，所以通常情况下是不会进行的。
 内存紧缩（memory compaction）：通过把所有的进程尽可能向某个方向移动，可能将小的空洞合成一大块，该技术被称为内存紧缩。  许多程序设计语言允许从堆中动态地分配内存，那么当进程空间试图增大时，交换技术可能会面临问题。为增长预留空间是一个解决方案。
5. 虚拟内存技术：分页 前面说过，重定位的效率不高，实际上该技术在内存管理上已经不太常用了。而交换技术也面临着进程空间膨胀的难题。虚拟内存技术是另一种可以解决内存超载问题的技术。该策略甚至能使程序在只有一部分被调入内存的情况下运行。
 虚拟内存（virtual memory）技术：将进程的虚拟地址空间分割成多个块，每块被称作一个页面（page）。每一页有连续的地址范围。这些页面被映射到物理内存（在物理内存中对应的单元称为页框page frame），但并不是所有的页面都必须在内存中才能运行程序。当进程引用到一部分在物理内存的页面时，由硬件立刻执行必要的映射。当进程引用到一部分不再物理内存的页面时，指令执行失败，进程陷入缺页中断，由OS负责将缺失的部分装入物理内存并重新执行失败的指令。内存和磁盘之间的交换总是以正规页面为单元进行的。  页面的大小一般从512B到64KB。
 页表：页表是一个数据结构，其目的是把page映射为page frame。从数学角度说，页表是一个函数，它的参数是虚拟页号，结果是page frame。注意，每个进程都拥有自己的页表。  上图展示了虚拟地址（虚拟页号&#43;页内偏移量）通过页表转换为物理地址（页框号&#43;页内偏移量）的过程。
在分页式系统中，有两个问题需要考虑：虚拟地址到物理地址的映射必须非常快；需要考虑应对虚拟地址空间很大的情况。
5.1 加速分页过程：TLB
通常，页表被设计在内存中，每次虚拟地址到物理地址的映射都必须访问内存，这样会导致性能低下。考虑将页表使用一组硬件快速寄存器实现是一种思路，但是考虑到昂贵的代价显然不可能将每个进程的页表都用这种方式实现。一个显而易见的方案是，使用一组硬件寄存器组成单一的页表，当启动一个进程时，操作系统将该进程在内存中的页表副本载入寄存器中。这样，该进程的地址映射过程中不再需要访问内存中的页表了，但是这样又增加了进程间切换时的开销。目前，一种常见的解决方案是使用TLB。
 TLB（Translation Lookaside Buffer，转换检测缓冲区）：“大多数程序总是对少量的页面进行多次访问”，基于这样的思想，在MMU中设置一个小型的硬件设备，它包含少量的表项，该设备就是TLB。地址映射首先在TLB中由硬件进行转换，如果TLB中匹配不到才会到去访问内存表项。  注意，最初，对TLB的管理和TLB失效处理都完全由MMU硬件来实现，只有在内存中没有找到某个页面时，才会陷入到操作系统中。后来，很多机器的几乎所有的页面管理都在软件中实现了。这些机器上，TLB表项被显示地装载。当发生TLB访问失效的时候不再是MMU到页表中查找并取出数据，而是生成一个TLB失效并将问题提交给操作系统解决。事实证明，如果TLB大（比如64个表项）到可以减少失效率，TLB的软件管理也能够变得足够有效。
5.2 处理巨大的虚拟地址空间：多级页表与倒排页表
以32位虚地址为例，后12位为偏移量，则页面大小为4KB，页面数量为2^20。
采用“多级页表”的原因是避免把全部页表一直保存在内存中，那些从不需要的页表项将被存储在磁盘。一般，页表级数不超过4级。
当虚拟地址空间是2^64字节时（64位计算机），假设页面大小是4KB，需要有2^52个表项。即使采用了多级页表，存储在磁盘上的表项数据所占用的空间也是巨额的。此时，解决方案之一是使用倒排页表（invertered page table）。在这种设计之中，实际内存里每一个页框有一个表项，而不是每一个虚拟页面有一个表项。"/>

<!--[if lte IE 9]>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
<![endif]-->

<!--[if lt IE 9]>
  <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->




</head>
<body>
  <div id="mobile-navbar" class="mobile-navbar">
  <div class="mobile-header-logo">
    <a href="/youzhilane/" class="logo">友知弄</a>
  </div>
  <div class="mobile-navbar-icon">
    <span></span>
    <span></span>
    <span></span>
  </div>
</div>
<nav id="mobile-menu" class="mobile-menu slideout-menu">
  <ul class="mobile-menu-list">
    <li class="mobile-menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/">主页</a>
          
        
      </li><li class="mobile-menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/categories/">分类</a>
          
        
      </li><li class="mobile-menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/booklist/">书单</a>
          
        
      </li><li class="mobile-menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/about/">关于友知弄</a>
          
        
      </li><li class="mobile-menu-item">
        
          
          
            <a class="menu-item-link" href="https://github.com/yixy" rel="noopener" target="_blank">
              GitHub
              
              <i class="iconfont">
                <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="18" height="18">
  <path d="M623.36 272.96 473.216 423.04C467.2 429.056 467.072 438.656 472.896 444.416c0 0-6.72-6.656 1.6 1.6C496.064 467.648 528.64 500.224 528.64 500.224 534.464 506.048 544 505.856 550.016 499.904l150.08-150.144 67.328 66.432c9.024 8.96 27.456 4.544 30.4-8.96 19.968-92.608 46.656-227.52 46.656-227.52 6.848-34.496-16.192-56.704-49.92-49.92 0 0-134.656 26.816-227.328 46.784C560.32 178.048 556.352 182.272 554.752 187.136c-3.2 6.208-3.008 14.208 3.776 20.992L623.36 272.96z"></path>
  <path d="M841.152 457.152c-30.528 0-54.784 24.512-54.784 54.656l0 274.752L237.696 786.56 237.696 237.696l206.016 0c6.656 0 10.752 0 13.248 0C487.68 237.696 512 213.184 512 182.848 512 152.32 487.36 128 456.96 128L183.04 128C153.216 128 128 152.576 128 182.848c0 3.136 0.256 6.272 0.768 9.28C128.256 195.136 128 198.272 128 201.408l0 639.488c0 0.064 0 0.192 0 0.256 0 0.128 0 0.192 0 0.32 0 30.528 24.512 54.784 54.784 54.784l646.976 0c6.592 0 9.728 0 11.712 0 28.736 0 52.928-22.976 54.464-51.968C896 843.264 896 842.304 896 841.344l0-20.352L896 561.408 896 512.128C896 481.792 871.424 457.152 841.152 457.152z"></path>
</svg>

              </i>
            </a>
          
        
      </li><li class="mobile-menu-item">
        
          
          <div class="mobile-menu-parent">
            <span class="mobile-submenu-open"></span>
            <a href="https://yixy.github.io/youzhilane/post/">
              归档
            </a>
          </div>
          <ul class="mobile-submenu-list">
            
              <li>
                <a href="https://yixy.github.io/youzhilane/post/">日期</a>
              </li>
            
              <li>
                <a href="https://yixy.github.io/youzhilane/tags/">标签</a>
              </li>
            
          </ul>
        
      </li>
    

    
  </ul>
</nav>


  
    






  <link rel="stylesheet" href="/youzhilane/lib/photoswipe/photoswipe.min.css" />
  <link rel="stylesheet" href="/youzhilane/lib/photoswipe/default-skin/default-skin.min.css" />




<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

<div class="pswp__bg"></div>

<div class="pswp__scroll-wrap">
    
    <div class="pswp__container">
      <div class="pswp__item"></div>
      <div class="pswp__item"></div>
      <div class="pswp__item"></div>
    </div>
    
    <div class="pswp__ui pswp__ui--hidden">
    <div class="pswp__top-bar">
      
      <div class="pswp__counter"></div>
      <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
      <button class="pswp__button pswp__button--share" title="Share"></button>
      <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
      <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
      
      
      <div class="pswp__preloader">
        <div class="pswp__preloader__icn">
          <div class="pswp__preloader__cut">
            <div class="pswp__preloader__donut"></div>
          </div>
        </div>
      </div>
    </div>
    <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
      <div class="pswp__share-tooltip"></div>
    </div>
    <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
    </button>
    <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
    </button>
    <div class="pswp__caption">
      <div class="pswp__caption__center"></div>
    </div>
    </div>
    </div>
</div>

  

  

  

  <header id="header" class="header container">
    <div class="logo-wrapper">
  <a href="/youzhilane/" class="logo">
    
      友知弄
    
  </a>
</div>

<nav class="site-navbar">
  <ul id="menu" class="menu">
    
    
        <li class="menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/">主页</a>
          

        

      </li>
    
        <li class="menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/categories/">分类</a>
          

        

      </li>
    
        <li class="menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/booklist/">书单</a>
          

        

      </li>
    
        <li class="menu-item">
        
          
          
            <a class="menu-item-link" href="https://yixy.github.io/youzhilane/about/">关于友知弄</a>
          

        

      </li>
    
        <li class="menu-item">
        
          
          
            <a class="menu-item-link" href="https://github.com/yixy" rel="noopener" target="_blank">
              GitHub
              
              <i class="iconfont">
                <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="18" height="18">
  <path d="M623.36 272.96 473.216 423.04C467.2 429.056 467.072 438.656 472.896 444.416c0 0-6.72-6.656 1.6 1.6C496.064 467.648 528.64 500.224 528.64 500.224 534.464 506.048 544 505.856 550.016 499.904l150.08-150.144 67.328 66.432c9.024 8.96 27.456 4.544 30.4-8.96 19.968-92.608 46.656-227.52 46.656-227.52 6.848-34.496-16.192-56.704-49.92-49.92 0 0-134.656 26.816-227.328 46.784C560.32 178.048 556.352 182.272 554.752 187.136c-3.2 6.208-3.008 14.208 3.776 20.992L623.36 272.96z"></path>
  <path d="M841.152 457.152c-30.528 0-54.784 24.512-54.784 54.656l0 274.752L237.696 786.56 237.696 237.696l206.016 0c6.656 0 10.752 0 13.248 0C487.68 237.696 512 213.184 512 182.848 512 152.32 487.36 128 456.96 128L183.04 128C153.216 128 128 152.576 128 182.848c0 3.136 0.256 6.272 0.768 9.28C128.256 195.136 128 198.272 128 201.408l0 639.488c0 0.064 0 0.192 0 0.256 0 0.128 0 0.192 0 0.32 0 30.528 24.512 54.784 54.784 54.784l646.976 0c6.592 0 9.728 0 11.712 0 28.736 0 52.928-22.976 54.464-51.968C896 843.264 896 842.304 896 841.344l0-20.352L896 561.408 896 512.128C896 481.792 871.424 457.152 841.152 457.152z"></path>
</svg>

              </i>
            </a>
          

        

      </li>
    
        <li class="menu-item">
        
          
          <a class="menu-item-link menu-parent" href="https://yixy.github.io/youzhilane/post/">归档</a>
          <ul class="submenu">
            
              <li>
                <a href="https://yixy.github.io/youzhilane/post/">日期</a>
              </li>
            
              <li>
                <a href="https://yixy.github.io/youzhilane/tags/">标签</a>
              </li>
            
          </ul>

        

      </li>
    

    
    

    
  </ul>
</nav>

  </header>

  <div id="mobile-panel">
    <main id="main" class="main bg-llight">
      <div class="content-wrapper">
        <div id="content" class="content container">
          <article class="post bg-white">
    
    <header class="post-header">
      <h1 class="post-title"></h1>
      
      <div class="post-meta">
        <time datetime="0001-01-01" class="post-time">
          0001-01-01
        </time>
        
        <span class="more-meta"> 约 66 字 </span>
          <span class="more-meta"> 预计阅读 1 分钟 </span>

        
        

        
        
      </div>
    </header>

    
    
<div class="post-toc" id="post-toc">
  <h2 class="post-toc-title">文章目录</h2>
  <div class="post-toc-content">
    <nav id="TableOfContents">
<ul>
<li><a href="#os笔记-7-内存的抽象与管理">OS笔记(7)——内存的抽象与管理</a>
<ul>
<li><a href="#1-无内存抽象">1. 无内存抽象</a></li>
<li><a href="#2-内存抽象-虚拟地址空间">2. 内存抽象：虚拟地址空间</a></li>
<li><a href="#3-内存地址重定位">3. 内存地址重定位</a></li>
<li><a href="#4-交换-swap-技术">4. 交换（swap）技术</a></li>
<li><a href="#5-虚拟内存技术-分页">5. 虚拟内存技术：分页</a></li>
<li><a href="#6-多维度的虚拟内存技术-分段">6. 多维度的虚拟内存技术：分段</a></li>
<li><a href="#7-参考">7. 参考</a></li>
</ul></li>
</ul>
</nav>
  </div>
</div>

    
    <div class="post-content">
      

<h1 id="os笔记-7-内存的抽象与管理">OS笔记(7)——内存的抽象与管理</h1>

<p>由于register和cache的管理由硬件完成，所以我们由内存管理开始我们对操作系统存储管理的介绍。</p>

<h2 id="1-无内存抽象">1. 无内存抽象</h2>

<p>最早的内存管理是直面物理内存的，即没有内存抽象。此时的内存组织方式出现过以下几种。</p>

<ul>
<li>“用户程序+RAM”：用于大型机和小型机。</li>
<li>“ROM+用户程序”：用于掌上设备或嵌入式设备。</li>
<li>“ROM+用户程序+RAM”：用于早期PC。</li>
</ul>

<p>直接使用物理内存面临两个问题，第一，用户可以寻址内存的每个字节，导致系统可以很容易地被（故意或偶然地）破坏，（除非使用特殊的硬件保护，如IBM360的锁键模式）；第二，系统想要并发运行多道程序是很困难的。</p>

<h2 id="2-内存抽象-虚拟地址空间">2. 内存抽象：虚拟地址空间</h2>

<p>用户程序在运行时其实不希望介入到复杂的存储器管理过程中，作为普通的程序，它需要的是一个简单的执行环境，有一个单一的地址空间、有自己的CPU，好像整个程序占有整个计算机而不用关心其它的程序（当然程序间通信的部分除外，因为这是程序主动要求跟其它程序通信和联系）。进程模型是对CPU的一个抽象，而地址空间则为程序创造了一种抽象的内存。</p>

<ul>
<li>虚拟地址空间：虚拟地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的虚拟地址空间，并且这个虚拟地址空间独立于其它进程的地址空间（除了在一些特殊情况下进程需要共享它们的地址空间外）。</li>
</ul>

<p>进程的虚拟地址并不是直接被送到内存总线上，而是被送到内存管理单元（MMU），MMU把虚拟地址映射为物理内存地址。</p>

<h2 id="3-内存地址重定位">3. 内存地址重定位</h2>

<p>可以采用重定位技术以支持多道程序在系统中运行。其中，动态重定位技术还提供了地址保护机制。</p>

<ul>
<li>静态重定位：指在程序执行之前，在装载过程中完成程序地址重定位。在程序装载到内存时，系统为每个程序地址加上一个偏移量常数。</li>
<li>动态重定位：指在程序运行中进行地址重定位。当一个进程运行时，程序在内存中的起始物理位置读取到基址寄存器中，程序的长度读取到界限寄存器中。进程每次访问内存时，CPU硬件会在把地址发送到内存总线前，自动把基址值加到进程发出的地址上，同时检查程序提供的地址是否合法（是否超过界限值）。</li>
</ul>

<p>静态重定位方式会减慢装载速度，并且没有地址保护机制。动态重定位具有地址保护机制，但是每次访问内存时需要进行加法和比较运算（加法在不使用特殊电路时会很慢），导致重定位效率低下。</p>

<h2 id="4-交换-swap-技术">4. 交换（swap）技术</h2>

<p>如果计算机物理内存足够大，可以保存所有进程，那么使用地址空间抽象并运用内存地址重定位技术似乎已经可以解决所有问题了。但实际上，所有进程所需的内存数量总是远远超出存储器能够支持的范围的。可以使用交换技术解决内存超载的问题。</p>

<ul>
<li>交换（swapping）技术：一个进程在内存中运行一段时间后，再将该进程保存到磁盘。这样，不在运行的进程就不会占用内存了。</li>
</ul>

<p>交换会在内存中产生很多空洞（hole）区域。可以采用内存紧缩的技术解决这种碎片化的空洞区，但是这个操作会耗费大量的CPU时间，所以通常情况下是不会进行的。</p>

<ul>
<li>内存紧缩（memory compaction）：通过把所有的进程尽可能向某个方向移动，可能将小的空洞合成一大块，该技术被称为内存紧缩。</li>
</ul>

<p>许多程序设计语言允许从堆中动态地分配内存，那么当进程空间试图增大时，交换技术可能会面临问题。为增长预留空间是一个解决方案。</p>

<h2 id="5-虚拟内存技术-分页">5. 虚拟内存技术：分页</h2>

<p>前面说过，重定位的效率不高，实际上该技术在内存管理上已经不太常用了。而交换技术也面临着进程空间膨胀的难题。虚拟内存技术是另一种可以解决内存超载问题的技术。该策略甚至能使程序在只有一部分被调入内存的情况下运行。</p>

<ul>
<li>虚拟内存（virtual memory）技术：将进程的虚拟地址空间分割成多个块，每块被称作一个页面（page）。每一页有连续的地址范围。这些页面被映射到物理内存（在物理内存中对应的单元称为页框page frame），但并不是所有的页面都必须在内存中才能运行程序。当进程引用到一部分在物理内存的页面时，由硬件立刻执行必要的映射。当进程引用到一部分不再物理内存的页面时，指令执行失败，进程陷入缺页中断，由OS负责将缺失的部分装入物理内存并重新执行失败的指令。内存和磁盘之间的交换总是以正规页面为单元进行的。</li>
</ul>

<p>页面的大小一般从512B到64KB。</p>

<ul>
<li>页表：页表是一个数据结构，其目的是把page映射为page frame。从数学角度说，页表是一个函数，它的参数是虚拟页号，结果是page frame。注意，每个进程都拥有自己的页表。</li>
</ul>

<p><img src="http://sweeat.me/pagetable.png" alt="页表" /></p>

<p>上图展示了虚拟地址（虚拟页号+页内偏移量）通过页表转换为物理地址（页框号+页内偏移量）的过程。</p>

<p>在分页式系统中，有两个问题需要考虑：虚拟地址到物理地址的映射必须非常快；需要考虑应对虚拟地址空间很大的情况。</p>

<p><strong>5.1 加速分页过程：TLB</strong></p>

<p>通常，页表被设计在内存中，每次虚拟地址到物理地址的映射都必须访问内存，这样会导致性能低下。考虑将页表使用一组硬件快速寄存器实现是一种思路，但是考虑到昂贵的代价显然不可能将每个进程的页表都用这种方式实现。一个显而易见的方案是，使用一组硬件寄存器组成单一的页表，当启动一个进程时，操作系统将该进程在内存中的页表副本载入寄存器中。这样，该进程的地址映射过程中不再需要访问内存中的页表了，但是这样又增加了进程间切换时的开销。目前，一种常见的解决方案是使用TLB。</p>

<ul>
<li>TLB（Translation Lookaside Buffer，转换检测缓冲区）：“大多数程序总是对少量的页面进行多次访问”，基于这样的思想，在MMU中设置一个小型的硬件设备，它包含少量的表项，该设备就是TLB。地址映射首先在TLB中由硬件进行转换，如果TLB中匹配不到才会到去访问内存表项。</li>
</ul>

<p>注意，最初，对TLB的管理和TLB失效处理都完全由MMU硬件来实现，只有在内存中没有找到某个页面时，才会陷入到操作系统中。后来，很多机器的几乎所有的页面管理都在软件中实现了。这些机器上，TLB表项被显示地装载。当发生TLB访问失效的时候不再是MMU到页表中查找并取出数据，而是生成一个TLB失效并将问题提交给操作系统解决。事实证明，如果TLB大（比如64个表项）到可以减少失效率，TLB的软件管理也能够变得足够有效。</p>

<p><strong>5.2 处理巨大的虚拟地址空间：多级页表与倒排页表</strong></p>

<p>以32位虚地址为例，后12位为偏移量，则页面大小为4KB，页面数量为2^20。</p>

<p>采用“多级页表”的原因是避免把全部页表一直保存在内存中，那些从不需要的页表项将被存储在磁盘。一般，页表级数不超过4级。</p>

<p>当虚拟地址空间是2^64字节时（64位计算机），假设页面大小是4KB，需要有2^52个表项。即使采用了多级页表，存储在磁盘上的表项数据所占用的空间也是巨额的。此时，解决方案之一是使用倒排页表（invertered page table）。在这种设计之中，实际内存里每一个页框有一个表项，而不是每一个虚拟页面有一个表项。</p>

<p><img src="http://sweeat.me/inverted_page_table.png" alt="倒排页表" /></p>

<p>采用倒排页表能够显著减少页表项，但是它使得从虚拟地址到物理地址的转换变得更困难，每次必须遍历整个页表来查找，而不是使用虚拟页号做索引。使用TLB能够缓解这个问题。但是当TLB失效时，还需要进行优化，此时可以使用虚拟地址来散列（确保不同散列值的数量与页表项数量相同，相同的散列值的表项使用链表相链）。</p>

<p><img src="http://sweeat.me/inverted_hash_page_table.png" alt="倒排hash页表" /></p>

<h2 id="6-多维度的虚拟内存技术-分段">6. 多维度的虚拟内存技术：分段</h2>

<p>到目前为止我们讨论的虚拟内存都是一维的，虚拟地址从0到最大地址，一个地址接着另一个地址。但是，对许多问题来说，有两个或多个独立的地址空间可能比只有一个要好得多。比如，一个编译器在编译过程中会建立许多表，其中可能包括1）源程序；2）符号表，包括变量名及其属性；3）包含常量的表；4）语法分析树；5）编译器内部过程调用使用的堆栈。其中，前4个表随编译的进行不断的增长，最后一个表则在编译过程中以一种不可预计的方式增长和缩小。想象一下，在一维存储器中，这5个表只能被分配到虚拟地址空间中连续的块中。这样带来的问题是，要么空间存在大量浪费（因为需要预留增长空间），要么用户程序需要手工对内存交换进行管理。</p>

<p>一个直观并且通用的方法是在机器上提供多个互相独立的称为段（segment）的地址空间。每个段由一个从0到最大的线性地址序列构成。各个段的长度可以是0到某个允许的最大值之间的任何一个值。不同的段的长度可以不同，并且通常情况下也都不相同。段的长度在运行期间可以动态改变。</p>

<p>需要强调的是，段是一个逻辑实体，程序员知道这一点并把它作为一个逻辑实体来使用。一个段可能包括一个过程、一个数组、一个堆栈、一组数值变量，但一般它不会同时包含多种不同类型的内容。</p>

<p><strong>段页式存储</strong></p>

<p>程序按逻辑块分段，段内再分页，内存仍以页为信息传送单位，这样的虚拟存储器被称为段页式虚拟存储器。在段页式虚拟存储器中，每个程序对应一个段表，每段对应一个页表，段的长度必须是页长的整数倍，段的起点必须是某一页的起点。</p>

<p>此时，虚拟地址由三部分组成（段号+段内页号+页内偏移量）。CPU根据虚拟地址访问时，首先根据段号得到段表地址；然后从段表中取出该段的页表起始地址，与虚拟地址中的段内页号合成，得到页表地址；最后从页表中取出实际页框号，与页内偏移量拼接形成实际地址。</p>

<h2 id="7-参考">7. 参考</h2>

<p>Berkeley，<a href="http://www.cs.virginia.edu/~cs333/notes/virtual_memory4.pdf">http://www.cs.virginia.edu/~cs333/notes/virtual_memory4.pdf</a></p>

    </div>

    
    
<div class="post-copyright">
  <p class="copyright-item">
    <span class="item-title">文章作者</span>
    <span class="item-content">yixy</span>
  </p>
  <p class="copyright-item">
    <span class="item-title">上次更新</span>
    <span class="item-content">
      0001-01-01
      
    </span>
  </p>
  
  <p class="copyright-item">
    <span class="item-title">许可协议</span>
    <span class="item-content"><a rel="license noopener" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank">CC BY-NC-ND 4.0</a></span>
  </p>
</div>


    
    
<div class="post-reward">
  <input type="checkbox" name="reward" id="reward" hidden />
  <label class="reward-button" for="reward">赞赏支持</label>
  <div class="qr-code">
    
    
      <label class="qr-code-image" for="reward">
        <img class="image" src="/youzhilane/img/about/wechat.jpg">
        <span>微信打赏</span>
      </label>
    
  </div>
</div>

    <footer class="post-footer">
      

      
      <nav class="post-nav">
        
          <a class="prev" href="/youzhilane/post/01%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/os%E7%AC%94%E8%AE%B05%E5%88%86%E5%B1%82%E5%AD%98%E5%82%A8%E4%BD%93%E7%B3%BB/">
            
            <i class="iconfont">
              <svg  class="icon" viewBox="0 0 1024 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="18" height="18">
  <path d="M691.908486 949.511495l75.369571-89.491197c10.963703-12.998035 10.285251-32.864502-1.499144-44.378743L479.499795 515.267417 757.434875 204.940602c11.338233-12.190647 11.035334-32.285311-0.638543-44.850487l-80.46666-86.564541c-11.680017-12.583596-30.356378-12.893658-41.662889-0.716314L257.233596 494.235404c-11.332093 12.183484-11.041474 32.266891 0.657986 44.844348l80.46666 86.564541c1.772366 1.910513 3.706415 3.533476 5.750981 4.877077l306.620399 321.703933C662.505829 963.726242 680.945807 962.528973 691.908486 949.511495z"></path>
</svg>

            </i>
            <span class="prev-text nav-default"></span>
            <span class="prev-text nav-mobile">上一篇</span>
          </a>
        
          <a class="next" href="/youzhilane/post/01%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/os%E7%AC%94%E8%AE%B07%E5%86%85%E5%AD%98%E5%8A%A8%E6%80%81%E5%88%86%E9%85%8D%E7%AE%97%E6%B3%95/">
            <span class="next-text nav-default"></span>
            <span class="prev-text nav-mobile">下一篇</span>
            
            <i class="iconfont">
              <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="18" height="18">
  <path d="M332.091514 74.487481l-75.369571 89.491197c-10.963703 12.998035-10.285251 32.864502 1.499144 44.378743l286.278095 300.375162L266.565125 819.058374c-11.338233 12.190647-11.035334 32.285311 0.638543 44.850487l80.46666 86.564541c11.680017 12.583596 30.356378 12.893658 41.662889 0.716314l377.434212-421.426145c11.332093-12.183484 11.041474-32.266891-0.657986-44.844348l-80.46666-86.564541c-1.772366-1.910513-3.706415-3.533476-5.750981-4.877077L373.270379 71.774697C361.493148 60.273758 343.054193 61.470003 332.091514 74.487481z"></path>
</svg>

            </i>
          </a>
      </nav>
    </footer>
  </article>

  
  
  
  

  
  

  

  
  

  

  

  

    

  

        </div>
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="icon-links">
  
  
    <a href="mailto:youzhilane01@gmail.com" rel="me noopener" class="iconfont"
      title="email" >
      <svg class="icon" viewBox="0 0 1451 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="36" height="36">
  <path d="M664.781909 681.472759 0 97.881301C0 3.997201 71.046997 0 71.046997 0L474.477909 0 961.649408 0 1361.641813 0C1361.641813 0 1432.688811 3.997201 1432.688811 97.881301L771.345323 681.472759C771.345323 681.472759 764.482731 685.154773 753.594283 688.65053L753.594283 688.664858C741.602731 693.493018 729.424896 695.068979 718.077952 694.839748 706.731093 695.068979 694.553173 693.493018 682.561621 688.664858L682.561621 688.65053C671.644501 685.140446 664.781909 681.472759 664.781909 681.472759L664.781909 681.472759ZM718.063616 811.603883C693.779541 811.016482 658.879232 802.205449 619.10784 767.734955 542.989056 701.759633 0 212.052267 0 212.052267L0 942.809523C0 942.809523 0 1024 83.726336 1024L682.532949 1024 753.579947 1024 1348.948139 1024C1432.688811 1024 1432.688811 942.809523 1432.688811 942.809523L1432.688811 212.052267C1432.688811 212.052267 893.138176 701.759633 817.019477 767.734955 777.248 802.205449 742.347691 811.03081 718.063616 811.603883L718.063616 811.603883Z"></path>
</svg>

    </a>


<a href="https://yixy.github.io/youzhilane/index.xml" rel="noopener alternate" type="application/rss&#43;xml"
    class="iconfont" title="rss" target="_blank">
    <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="30" height="30">
  <path d="M819.157333 1024C819.157333 574.592 449.408 204.8 0 204.8V0c561.706667 0 1024 462.293333 1024 1024h-204.842667zM140.416 743.04a140.8 140.8 0 0 1 140.501333 140.586667A140.928 140.928 0 0 1 140.074667 1024C62.72 1024 0 961.109333 0 883.626667s62.933333-140.544 140.416-140.586667zM678.784 1024h-199.04c0-263.210667-216.533333-479.786667-479.744-479.786667V345.173333c372.352 0 678.784 306.517333 678.784 678.826667z"></path>
</svg>

  </a>
   
</div>

<div class="copyright">
  <span class="power-by">
    Powered by <a class="hexo-link" href="https://gohugo.io">Hugo</a>
  </span>
  <span class="division">|</span>
  <span class="theme-info">
    Theme - <a class="theme-link" href="https://github.com/xianmin/hugo-theme-jane">Jane</a>
  </span>

  <span class="copyright-year">
    &copy;
    2019
    <span class="heart">
      
      <i class="iconfont">
        <svg class="icon" viewBox="0 0 1025 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="14" height="14">
  <path d="M1000.1 247.9c-15.5-37.3-37.6-70.6-65.7-98.9-54.4-54.8-125.8-85-201-85-85.7 0-166 39-221.4 107.4C456.6 103 376.3 64 290.6 64c-75.1 0-146.5 30.4-201.1 85.6-28.2 28.5-50.4 61.9-65.8 99.3-16 38.8-24 79.9-23.6 122.2 0.7 91.7 40.1 177.2 108.1 234.8 3.1 2.6 6 5.1 8.9 7.8 14.9 13.4 58 52.8 112.6 102.7 93.5 85.5 209.9 191.9 257.5 234.2 7 6.1 15.8 9.5 24.9 9.5 9.2 0 18.1-3.4 24.9-9.5 34.5-30.7 105.8-95.9 181.4-165 74.2-67.8 150.9-138 195.8-178.2 69.5-57.9 109.6-144.4 109.9-237.3 0.1-42.5-8-83.6-24-122.2z"
   fill="#8a8a8a"></path>
</svg>

      </i>
    </span><span class="author">
        yixy
        
      </span></span>

  
  

  
</div>

    </footer>

    <div class="back-to-top" id="back-to-top">
      <i class="iconfont">
        
        <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  width="35" height="35">
  <path d="M510.866688 227.694839 95.449397 629.218702l235.761562 0-2.057869 328.796468 362.40389 0L691.55698 628.188232l241.942331-3.089361L510.866688 227.694839zM63.840492 63.962777l894.052392 0 0 131.813095L63.840492 195.775872 63.840492 63.962777 63.840492 63.962777zM63.840492 63.962777"></path>
</svg>

      </i>
    </div>
  </div>
  
<script type="text/javascript" src="/youzhilane/lib/jquery/jquery-3.2.1.min.js"></script>
  <script type="text/javascript" src="/youzhilane/lib/slideout/slideout-1.0.1.min.js"></script>




<script type="text/javascript" src="/youzhilane/js/main.638251f4230630f0335d8c6748e53a96f94b72670920b60c09a56fdc8bece214.js" integrity="sha256-Y4JR9CMGMPAzXYxnSOU6lvlLcmcJILYMCaVv3Ivs4hQ=" crossorigin="anonymous"></script>












  
    <script type="text/javascript" src="/youzhilane/js/load-photoswipe.js"></script>
    <script type="text/javascript" src="/youzhilane/lib/photoswipe/photoswipe.min.js"></script>
    <script type="text/javascript" src="/youzhilane/lib/photoswipe/photoswipe-ui-default.min.js"></script>
  















</body>
</html>
